package olga.gorbatiuk.perdep.logger.impl;

import java.util.Arrays;
import java.util.Date;

import olga.gorbatiuk.perdep.logger.Journal;
import olga.gorbatiuk.perdep.logger.exceptions.IllegalRangeException;
import olga.gorbatiuk.perdep.logger.record.Record;
import olga.gorbatiuk.perdep.logger.record.comparator.ByDateAndImportanceComparator;
import olga.gorbatiuk.perdep.logger.record.comparator.ByDateComparator;

public class ArrayJournal implements Journal {

    private Record[] recordArray;
    private int size;
    private int capacity;

    public ArrayJournal() {
        this.size = 0;
        this.capacity = 0; // пока нет ни одного элемента
        this.recordArray = new Record[capacity];
    }

    public ArrayJournal(Journal otherJournal) {
        final int otherJournalSize = otherJournal.size();

        this.size = otherJournalSize;
        this.capacity = otherJournalSize;
        Record[] recordArray = new Record[otherJournalSize];

        for (int i = 0; i < otherJournalSize; i++) {
            recordArray[i] = otherJournal.get(i);
        }

        this.recordArray = recordArray;
    }

    @Override
    public void add(Record record) {
        if (capacity == size) {
            capacity = (capacity * 3) / 2 + 1;
            Record[] tempRecordArray = recordArray;
            recordArray = new Record[capacity];
            System.arraycopy(tempRecordArray, 0, recordArray, 0, size);
        }
        recordArray[size++] = record;
    }

    @Override
    public void add(Journal journal) {
        if (journal.getClass() == this.getClass()) {
            ArrayJournal otherArrayJournal = (ArrayJournal) journal;

            for (int i = 0; i < otherArrayJournal.size(); i++) {
                add(otherArrayJournal.get(i));
            }
        }
    }

    @Override
    public void remove(Record r) {
        for (int i = 0; i < recordArray.length; i++) {
            if (recordArray[i].equals(r)) {
                remove(i);
                return;
            }
        }
    }

    @Override
    public void remove(int index) {
        int numMuoved = size - index - 1;
        System.arraycopy(recordArray, index + 1, recordArray, index, numMuoved);
        recordArray[--size] = null;
    }

    @Override
    public Record get(int index) {
        return recordArray[index];
    }

    @Override
    public void set(int index, Record record) {
        recordArray[index] = record;
    }

    @Override
    public void insert(int index, Record record) {
        if (capacity == size) {
            capacity = (capacity * 3) / 2 + 1;
            Record[] tempRecordArray = recordArray;
            recordArray = new Record[capacity];
            System.arraycopy(tempRecordArray, 0, recordArray, 0, size);
        }
        System.arraycopy(recordArray, index, recordArray, index + 1, size
                - index);
        recordArray[index] = record;
        size++;
    }

    @Override
    public void remove(int fromIndex, int toIndex) throws IllegalRangeException {
        if ((fromIndex < 0) || (toIndex < 0) || (fromIndex > toIndex) || (fromIndex > size) || (toIndex > size)) {
            throw new IllegalRangeException("Illegal range. The range must be in range from 0 to array's length.");
        }
        int delta = toIndex - fromIndex + 1;
        for (int i = fromIndex; i < size - delta; i++) {
            recordArray[i] = recordArray[i + delta];
        }
        for (int i = size - delta; i < size; i++) {
            recordArray[i] = null;
        }
        size -= delta;

    }

    @Override
    public void removeAll() {
        size = 0;
        capacity = 0;
        recordArray = new Record[capacity];
    }

    @Override
    public int size() {
        return size;
    }

    @Override
    public Journal filter(String s) {
        Journal newJournal = new ArrayJournal();
        for (int i = 0; i < size; i++) {
            if (recordArray[i].toString().contains(s)) {
                newJournal.add(recordArray[i]);
            }
        }
        return newJournal;
    }

    @Override
    public Journal filter(Date fromDate, Date toDate) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void sortByDate() {
        Arrays.sort(recordArray, 0, size, new ByDateComparator());
    }

    @Override
    public void sortByImportanceDate() {
        Arrays.sort(recordArray, 0, size, new ByDateAndImportanceComparator());
    }

    @Override
    public void sortByImportanceSourceDate() {
        // TODO Auto-generated method stub

    }

    @Override
    public void sortBySourceDate() {
        // TODO Auto-generated method stub

    }

    @Override
    public void printRecords() {
        for (Record record : recordArray) {
            System.out.println(record.toString());
        }
    }

}
